#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <sys/poll.h>
#include <sys/time.h>
#include <sys/select.h>
#include <fcntl.h>
#include <errno.h>
#include <math.h>
#include <unistd.h>
#include <sys/prctl.h>

#include "libmov/mov-format.h"
#include "audio_aac_adp.h"
#include "plug_media_ai.h"
#include "plug_media_ao.h"
#include "hi_comm_rc.h"
#include "sample_comm.h"
#include "plug_fmp4muxer.h"
#include "hi_ext_util.h"
#include "plug_media_recordmng.h"

#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif
#endif /* End of #ifdef __cplusplus */

typedef struct tagPLUG_MEDIA_VPSSCFG_S
{
    HI_S32 s32VpssGrp;
    HI_S32 s32VpssChn;
    VPSS_GRP_ATTR_S stGrpAttr;
    VPSS_CHN_ATTR_S stChnAttr;
}PLUG_MEDIA_VPSSCFG_S;

typedef struct tagPLUG_MEDIA_VENCCFG_S
{
    HI_S32 s32VencChn;
    VENC_CHN_ATTR_S stChnAttr;
}PLUG_MEDIA_VENCCFG_S;

static HI_BOOL gs_bRecord = HI_FALSE;
static HI_HANDLE pFMP4Muxer = HI_NULL;

static HI_S32 PLUG_MEDIA_VENC_SaveStream(VENC_STREAM_S* pstStream)
{
    HI_S32 i;
    HI_S32 s32Ret = HI_SUCCESS;
    HI_S32 s32TimeMs = 0;
    struct timeval stTimeNowUs;
    gettimeofday(&stTimeNowUs, NULL);;
    s32TimeMs = stTimeNowUs.tv_sec * 1000 + stTimeNowUs.tv_usec / 1000;

    for (i = 0; i < pstStream->u32PackCount; i++)
    {
        s32Ret = FMP4MUXER_Write(pFMP4Muxer, FMP4MUXER_TRACK_TYPE_VIDEO, 
            pstStream->pstPack[i].pu8Addr + pstStream->pstPack[i].u32Offset,
            pstStream->pstPack[i].u32Len - pstStream->pstPack[i].u32Offset,
            s32TimeMs, s32TimeMs, 
            //pstStream->pstPack[i].DataType.enH264EType);
            //pstStream->pstPack[i].u64PTS / 1000, pstStream->pstPack[i].u64PTS / 1000,
            (BASE_IDRSLICE == pstStream->stH264Info.enRefType)?HI_TRUE:HI_FALSE);
        if (HI_SUCCESS != s32Ret)
        {
            LOGE("FMP4MUXER_Write failed, [%d]\n", s32Ret);
        }
    }

    return HI_SUCCESS;
}


static HI_S32 RECORDMNG_GetVpssCfg(PLUG_MEDIA_VPSSCFG_S *pstVpssCfg)
{

    pstVpssCfg->s32VpssGrp = 5;
    pstVpssCfg->s32VpssChn = 1;

    memset(&pstVpssCfg->stGrpAttr, 0, sizeof(VPSS_GRP_ATTR_S));
    pstVpssCfg->stGrpAttr.enDynamicRange = DYNAMIC_RANGE_SDR8;
    pstVpssCfg->stGrpAttr.enPixelFormat  = PIXEL_FORMAT_YVU_SEMIPLANAR_420;
    pstVpssCfg->stGrpAttr.u32MaxW = 2592;
    pstVpssCfg->stGrpAttr.u32MaxH  = 1944;
    pstVpssCfg->stGrpAttr.stFrameRate.s32SrcFrameRate = -1;
    pstVpssCfg->stGrpAttr.stFrameRate.s32DstFrameRate = -1;
    pstVpssCfg->stGrpAttr.bNrEn = HI_TRUE;
    pstVpssCfg->stGrpAttr.stNrAttr.enNrType = VPSS_NR_TYPE_VIDEO;
    pstVpssCfg->stGrpAttr.stNrAttr.enNrMotionMode = NR_MOTION_MODE_NORMAL;
    pstVpssCfg->stGrpAttr.stNrAttr.enCompressMode = COMPRESS_MODE_FRAME;

    memset(&pstVpssCfg->stChnAttr, 0, sizeof(VPSS_CHN_ATTR_S));
    pstVpssCfg->stChnAttr.u32Width = 1920;
    pstVpssCfg->stChnAttr.u32Height = 1080;
    pstVpssCfg->stChnAttr.enChnMode = VPSS_CHN_MODE_USER;
    pstVpssCfg->stChnAttr.enCompressMode = COMPRESS_MODE_NONE;//COMPRESS_MODE_SEG;
    pstVpssCfg->stChnAttr.enDynamicRange = DYNAMIC_RANGE_SDR8;
    pstVpssCfg->stChnAttr.enPixelFormat = PIXEL_FORMAT_YVU_SEMIPLANAR_420;
    pstVpssCfg->stChnAttr.stFrameRate.s32SrcFrameRate = -1;
    pstVpssCfg->stChnAttr.stFrameRate.s32DstFrameRate = -1;
    pstVpssCfg->stChnAttr.u32Depth                     = 0;
    pstVpssCfg->stChnAttr.bMirror                      = HI_FALSE;
    pstVpssCfg->stChnAttr.bFlip                        = HI_FALSE;
    pstVpssCfg->stChnAttr.enVideoFormat                = VIDEO_FORMAT_LINEAR;
    pstVpssCfg->stChnAttr.stAspectRatio.enMode         = ASPECT_RATIO_NONE;

    return HI_SUCCESS;
}

static HI_S32 PLUG_MEDIA_VpssInit(PLUG_MEDIA_VPSSCFG_S *pstVpssCfg)
{
    if (HI_NULL == pstVpssCfg)
    {
        LOGE("input null\n");
        return HI_FAILURE;
    }

    HI_S32 s32Ret = HI_SUCCESS;
    VPSS_GRP s32VpssGrp = pstVpssCfg->s32VpssGrp;
    VPSS_CHN s32VpssChn = pstVpssCfg->s32VpssChn;

    s32Ret = HI_MPI_VPSS_CreateGrp(s32VpssGrp, &pstVpssCfg->stGrpAttr);
    if (s32Ret != HI_SUCCESS)
    {
        SAMPLE_PRT("HI_MPI_VPSS_CreateGrp(grp:%d) failed with %#x!\n", s32VpssGrp, s32Ret);
        return HI_FAILURE;
    }

    s32Ret = HI_MPI_VPSS_SetChnAttr(s32VpssGrp, s32VpssChn, &pstVpssCfg->stChnAttr);
    
    if (s32Ret != HI_SUCCESS)
    {
        SAMPLE_PRT("HI_MPI_VPSS_SetChnAttr(grp:%d, chn:%d) failed with %#x\n", s32VpssGrp, s32VpssChn, s32Ret);
        return HI_FAILURE;
    }

    s32Ret = HI_MPI_VPSS_EnableChn(s32VpssGrp, s32VpssChn);
    if (s32Ret != HI_SUCCESS)
    {
        SAMPLE_PRT("HI_MPI_VPSS_EnableChn(grp:%d, chn:%d) failed with %#x\n", s32VpssGrp, s32VpssChn, s32Ret);
        return HI_FAILURE;
    }

    s32Ret = HI_MPI_VPSS_StartGrp(s32VpssGrp);
    if (s32Ret != HI_SUCCESS)
    {
        SAMPLE_PRT("HI_MPI_VPSS_StartGrp(grp:%d) failed with %#x\n", s32VpssGrp, s32Ret);
        return HI_FAILURE;
    }

    return HI_SUCCESS;
}

static HI_S32 RECORDMNG_GetVencCfg(PLUG_MEDIA_VENCCFG_S *pstVencCfg)
{
    pstVencCfg->s32VencChn = 5;
#if 0
    /* venc attr */
    memset(&pstVencCfg->stChnAttr, 0, sizeof(VENC_CHN_ATTR_S));
    pstVencCfg->stChnAttr.stVencAttr.enType          = PT_H264;
    pstVencCfg->stChnAttr.stVencAttr.u32MaxPicWidth  = 2592;
    pstVencCfg->stChnAttr.stVencAttr.u32MaxPicHeight = 1944;
    pstVencCfg->stChnAttr.stVencAttr.u32PicWidth     = 2592;/*the picture width*/
    pstVencCfg->stChnAttr.stVencAttr.u32PicHeight    = 1944;/*the picture height*/
    pstVencCfg->stChnAttr.stVencAttr.u32BufSize      = 2592 * 1944 * 3;/*stream buffer size*/
    pstVencCfg->stChnAttr.stVencAttr.u32Profile      = 30;
    pstVencCfg->stChnAttr.stVencAttr.bByFrame        = HI_TRUE;/*get stream mode is slice mode or frame mode?*/

    /* gop */
    pstVencCfg->stChnAttr.stGopAttr.enGopMode = VENC_GOPMODE_NORMALP;
    pstVencCfg->stChnAttr.stGopAttr.stNormalP.s32IPQpDelta = 1;

    /* rc mode */
    VENC_H264_CBR_S    stH264Cbr;
    pstVencCfg->stChnAttr.stRcAttr.enRcMode = VENC_RC_MODE_H264CBR;
    stH264Cbr.u32Gop                = 30; /*the interval of IFrame*/
    stH264Cbr.u32StatTime           = 1; /* stream rate statics time(s) */
    stH264Cbr.u32SrcFrameRate       = 30; /* input (vi) frame rate */
    stH264Cbr.fr32DstFrameRate      = 30; /* target frame rate */
    stH264Cbr.u32BitRate = 1000 * 4;

    memcpy(&pstVencCfg->stChnAttr.stRcAttr.stH264Cbr, &stH264Cbr, sizeof(VENC_H264_CBR_S));
#else
    HI_MPI_VENC_GetChnAttr(0, &pstVencCfg->stChnAttr);
#endif

    return HI_SUCCESS;
}

static HI_S32 PLUG_MEDIA_VencInit(PLUG_MEDIA_VENCCFG_S *pstVencCfg)
{
    HI_S32 s32Ret = HI_SUCCESS;
    VENC_CHN s32VencChn = pstVencCfg->s32VencChn;
    VENC_RECV_PIC_PARAM_S stRecvParam;

    s32Ret = HI_MPI_VENC_CreateChn(s32VencChn, &pstVencCfg->stChnAttr);
    if (HI_SUCCESS != s32Ret)
    {
        SAMPLE_PRT("HI_MPI_VENC_CreateChn [%d] faild with %#x! ===\n", \
                   s32VencChn, s32Ret);
        return s32Ret;
    }

    s32Ret = SAMPLE_COMM_VENC_CloseReEncode(s32VencChn);
    if (HI_SUCCESS != s32Ret)
    {
        HI_MPI_VENC_DestroyChn(s32VencChn);
        return s32Ret;
    }

    stRecvParam.s32RecvPicNum = -1;
    s32Ret = HI_MPI_VENC_StartRecvFrame(s32VencChn, &stRecvParam);
    if (HI_SUCCESS != s32Ret)
    {
        SAMPLE_PRT("HI_MPI_VENC_StartRecvPic faild with%#x! \n", s32Ret);
        return HI_FAILURE;
    }
    LOGI("VENC[%d] started\n", s32VencChn);

    return HI_SUCCESS;
}

static HI_VOID* PLUG_MEDIA_VENC_GetVencStreamProc(HI_VOID* args)
{
    pthread_detach(pthread_self());

    HI_S32 maxfd = 0;
    struct timeval TimeoutVal;
    fd_set read_fds;
    HI_U32 u32PictureCnt = 0;
    HI_S32 VencFd;
    HI_CHAR aszFileName[64];
    FILE* pFile = HI_NULL;
    HI_CHAR szFilePostfix[10] = ".h264";
    VENC_CHN_STATUS_S stStat;
    VENC_STREAM_S stStream;
    HI_S32 s32Ret;
    PAYLOAD_TYPE_E enPayLoadType;
    VENC_STREAM_BUF_INFO_S stStreamBufInfo;

    prctl(PR_SET_NAME, "GetVencStream", 0,0,0);

    PLUG_MEDIA_VENCCFG_S stVencCfg = { 0 };

    s32Ret = RECORDMNG_GetVencCfg(&stVencCfg);
    if (HI_SUCCESS != s32Ret)
    {
        LOGE("RECORDMNG_GetVencCfg failed\n");
        return HI_NULL;
    }

    /******************************************
     step 1:  check & prepare save-file & venc-fd
    ******************************************/
    /* decide the stream file name, and open file to save stream */
    s32Ret = HI_MPI_VENC_GetChnAttr(stVencCfg.s32VencChn, &stVencCfg.stChnAttr);
    if (s32Ret != HI_SUCCESS)
    {
        SAMPLE_PRT("HI_MPI_VENC_GetChnAttr chn[%d] failed with %#x!\n", \
                   stVencCfg.s32VencChn, s32Ret);
        return NULL;
    }
    enPayLoadType = stVencCfg.stChnAttr.stVencAttr.enType;

    /* Set Venc Fd. */
    VencFd = HI_MPI_VENC_GetFd(stVencCfg.s32VencChn);
    if (VencFd < 0)
    {
        SAMPLE_PRT("HI_MPI_VENC_GetFd failed with %#x!\n",
                   VencFd);
        return NULL;
    }
    if (maxfd <= VencFd)
    {
        maxfd = VencFd;
    }

    s32Ret = HI_MPI_VENC_GetStreamBufInfo (stVencCfg.s32VencChn, &stStreamBufInfo);
    if (HI_SUCCESS != s32Ret)
    {
        SAMPLE_PRT("HI_MPI_VENC_GetStreamBufInfo failed with %#x!\n", s32Ret);
        return (void *)HI_FAILURE;
    }

    /******************************************
     step 2:  Start to get streams of each channel.
    ******************************************/
    while (HI_TRUE == gs_bRecord)
    {
        FD_ZERO(&read_fds);
        FD_SET(VencFd, &read_fds);

        TimeoutVal.tv_sec  = 2;
        TimeoutVal.tv_usec = 0;
        s32Ret = select(maxfd + 1, &read_fds, NULL, NULL, &TimeoutVal);
        if (s32Ret < 0)
        {
            SAMPLE_PRT("select failed!\n");
            break;
        }
        else if (s32Ret == 0)
        {
            SAMPLE_PRT("get venc stream time out, exit thread\n");
            continue;
        }
        else
        {
            if (FD_ISSET(VencFd, &read_fds))
            {
                /*******************************************************
                 step 2.1 : query how many packs in one-frame stream.
                *******************************************************/
                memset(&stStream, 0, sizeof(stStream));

                s32Ret = HI_MPI_VENC_QueryStatus(stVencCfg.s32VencChn, &stStat);
                if (HI_SUCCESS != s32Ret)
                {
                    SAMPLE_PRT("HI_MPI_VENC_QueryStatus chn[%d] failed with %#x!\n", stVencCfg.s32VencChn, s32Ret);
                    break;
                }

                if(0 == stStat.u32CurPacks)
                {
                      SAMPLE_PRT("NOTE: Current  frame is NULL!\n");
                      continue;
                }
                /*******************************************************
                 step 2.3 : malloc corresponding number of pack nodes.
                *******************************************************/
                stStream.pstPack = (VENC_PACK_S*)malloc(sizeof(VENC_PACK_S) * stStat.u32CurPacks);
                if (NULL == stStream.pstPack)
                {
                    SAMPLE_PRT("malloc stream pack failed!\n");
                    break;
                }

                /*******************************************************
                 step 2.4 : call mpi to get one-frame stream
                *******************************************************/
                stStream.u32PackCount = stStat.u32CurPacks;
                s32Ret = HI_MPI_VENC_GetStream(stVencCfg.s32VencChn, &stStream, HI_TRUE);
                if (HI_SUCCESS != s32Ret)
                {
                    free(stStream.pstPack);
                    stStream.pstPack = NULL;
                    SAMPLE_PRT("HI_MPI_VENC_GetStream failed with %#x!\n", \
                               s32Ret);
                    break;
                }

                /*******************************************************
                 step 2.5 : save frame to file
                *******************************************************/
                s32Ret = PLUG_MEDIA_VENC_SaveStream(&stStream);

                if (HI_SUCCESS != s32Ret)
                {
                    free(stStream.pstPack);
                    stStream.pstPack = NULL;
                    SAMPLE_PRT("save stream failed!\n");
                    break;
                }
                /*******************************************************
                 step 2.6 : release stream
                 *******************************************************/
                s32Ret = HI_MPI_VENC_ReleaseStream(stVencCfg.s32VencChn, &stStream);
                if (HI_SUCCESS != s32Ret)
                {
                    SAMPLE_PRT("HI_MPI_VENC_ReleaseStream failed!\n");
                    free(stStream.pstPack);
                    stStream.pstPack = NULL;
                    break;
                }

                /*******************************************************
                 step 2.7 : free pack nodes
                *******************************************************/
                free(stStream.pstPack);
                stStream.pstPack = NULL;
            }
        }
    }

    LOGI("venc get frame thread exit\n");
    return NULL;
}


HI_S32 PLUG_MEDIA_RECORDMNG_Init(PLUG_MEDIA_RECORDMNG_INITCFG_S *pstInitCfg)
{
    //初始化媒体通道，参数目前为空，默认写死
    HI_S32 s32Ret = HI_SUCCESS;
    PLUG_MEDIA_VPSSCFG_S stVpssCfg = { 0 };
    PLUG_MEDIA_VENCCFG_S stVencCfg = { 0 };
    s32Ret = RECORDMNG_GetVpssCfg(&stVpssCfg);
    if (HI_SUCCESS != s32Ret)
    {
        LOGE("PHOTOMNG_GetVpssCfg failed\n");
        return HI_FAILURE;
    }

    s32Ret = RECORDMNG_GetVencCfg(&stVencCfg);
    if (HI_SUCCESS != s32Ret)
    {
        LOGE("RECORDMNG_GetVencCfg failed\n");
        return HI_FAILURE;
    }

    s32Ret = PLUG_MEDIA_VpssInit(&stVpssCfg);
    if (HI_SUCCESS != s32Ret)
    {
        LOGE("PLUG_MEDIA_VpssInit failed\n");
        return HI_FAILURE;
    }

    s32Ret = SAMPLE_COMM_VI_Bind_VPSS(0, 0, stVpssCfg.s32VpssGrp);
    if (s32Ret != HI_SUCCESS)
    {
        SAMPLE_PRT("SAMPLE_COMM_VI_Bind_VPSS(grp:%d) failed with %#x\n", stVpssCfg.s32VpssGrp, s32Ret);
        return HI_FAILURE;
    }

    s32Ret = PLUG_MEDIA_VencInit(&stVencCfg);
    if (HI_SUCCESS != s32Ret)
    {
        LOGE("PLUG_MEDIA_VencInit failed\n");
        return HI_FAILURE;
    }

    s32Ret = SAMPLE_COMM_VPSS_Bind_VENC(stVpssCfg.s32VpssGrp, stVpssCfg.s32VpssChn, stVencCfg.s32VencChn);
    if (HI_SUCCESS != s32Ret)
    {
        SAMPLE_PRT("SAMPLE_COMM_VPSS_Bind_VENC vpssgrp %d, vpsschn %d, venc chn %d failed for %#x!\n",
            stVpssCfg.s32VpssGrp, stVpssCfg.stChnAttr, stVencCfg.s32VencChn, s32Ret);
        return HI_FAILURE;
    }

    s32Ret = FMP4MUXER_Init();
    if (HI_SUCCESS != s32Ret)
    {
        LOGE("FMP4MUXER_Init failed\n");
        return HI_FAILURE;
    }

    return HI_SUCCESS;
}

HI_S32 PLUG_MEDIA_RECORDMNG_StartRecord(PLUG_MEDIA_RECORDMNG_CFG_S *pstRecordCfg)
{
    //从venc获取h264或h265数据流，通过fmp4封装后写到指定路径
    HI_S32 s32Ret = HI_SUCCESS;
    pthread_t tVencPid;
    PLUG_MEDIA_VENCCFG_S stVencCfg = { 0 };
    FMP4MUXER_VIDEO_ENCODER_ATTR_S stVideoAttr;
    FMP4MUXER_AUDIO_ENCODER_ATTR_S stAudioAttr;

    if (gs_bRecord)
    {
        LOGI("Record started, return HI_SUCCESS\n");
        return HI_SUCCESS;
    }

    stAudioAttr.s32BitsPerSample = AACLC_SAMPLES_PER_FRAME;
    stAudioAttr.s32ChannelCount = 1;
    stAudioAttr.s32SampleRate = AUDIO_SAMPLE_RATE_48000;

    s32Ret = RECORDMNG_GetVencCfg(&stVencCfg);
    if (HI_SUCCESS != s32Ret)
    {
        LOGE("RECORDMNG_GetVencCfg failed\n");
        return HI_FAILURE;
    }

    stVideoAttr.s32Width = stVencCfg.stChnAttr.stVencAttr.u32PicWidth;
    stVideoAttr.s32Height = stVencCfg.stChnAttr.stVencAttr.u32PicHeight;

    switch(stVencCfg.stChnAttr.stVencAttr.enType)
    {
        case PT_H264:
            stVideoAttr.enType = FMP4MUXER_VIDEO_TYPE_H264;
            break;
        case PT_H265:
            stVideoAttr.enType = FMP4MUXER_VIDEO_TYPE_H265;
            break;
        default:
            LOGE("Unsupported video payload[%d]\n", stVencCfg.stChnAttr.stVencAttr.enType);
            return HI_FAILURE;
    }

    s32Ret = FMP4MUXER_Create(pstRecordCfg->azFilePath, &stVideoAttr, &stAudioAttr, &pFMP4Muxer);
    if (HI_SUCCESS != s32Ret)
    {
        LOGE("FMP4MUXER_Create failed\n");
        return HI_FAILURE;
    }

    gs_bRecord = HI_TRUE;
    s32Ret = pthread_create(&tVencPid, 0, PLUG_MEDIA_VENC_GetVencStreamProc, HI_NULL);
    if (HI_SUCCESS != s32Ret)
    {
        LOGE("PLUG_MEDIA_VENC_GetVencStreamProc thread create failed\n");
        gs_bRecord = HI_FALSE;
        return HI_FAILURE;
    }

    s32Ret = PLUG_MEDIA_AO_SystemSound(PLUG_MEDIA_AO_SOUND_START_RECODE);
    if (HI_SUCCESS != s32Ret)
    {
        LOGE("PLUG_MEDIA_AO_SystemSound failed\n");
    }

    return HI_SUCCESS;
}

HI_S32 PLUG_MEDIA_RECORDMNG_StopRecord(HI_VOID)
{
    //停止录像
    HI_S32 s32Ret = HI_SUCCESS;
    if (!gs_bRecord)
    {
        LOGI("Record already stopped, return HI_SUCCESS\n");
        return HI_SUCCESS;
    }
    gs_bRecord = HI_FALSE;
    sleep(2);
    s32Ret = FMP4MUXER_Close(pFMP4Muxer);
    if (HI_SUCCESS != s32Ret)
    {
        LOGE("FMP4MUXER_Close failed\n");
    }

    pFMP4Muxer = HI_NULL;

    s32Ret = PLUG_MEDIA_AO_SystemSound(PLUG_MEDIA_AO_SOUND_STOP_RECODE);
    if (HI_SUCCESS != s32Ret)
    {
        LOGE("PLUG_MEDIA_AO_SystemSound failed\n");
    }

    return HI_SUCCESS;
}

HI_S32 PLUG_MEDIA_RecordSendAudioFrame(PLUG_COMMON_AI_DATA_INFO* pstAiData)
{
    return HI_SUCCESS;

    if (HI_NULL == pstAiData)
    {
        LOGI("Input Null\n");
        return HI_FAILURE;
    }

    if (HI_FALSE == gs_bRecord)
    {
        LOGD("Not started, return HI_SUCCESS\n");
        return HI_SUCCESS;
    }

    HI_S32 s32Ret = HI_SUCCESS;
    HI_S32 s32TimeMs = 0;
    struct timeval stTimeNowUs;
    gettimeofday(&stTimeNowUs, NULL);;
    s32TimeMs = stTimeNowUs.tv_sec * 1000 + stTimeNowUs.tv_usec / 1000;

    s32Ret = FMP4MUXER_Write(pFMP4Muxer, FMP4MUXER_TRACK_TYPE_AUDIO, 
        pstAiData->pu8Buff, pstAiData->s32Bufflen,
        s32TimeMs, s32TimeMs, MOV_AV_FLAG_KEYFREAME);
        //pstAiData->u64Pts / 1000, pstAiData->u64Pts / 1000, HI_FALSE);
    if (HI_SUCCESS != s32Ret)
    {
        LOGE("FMP4MUXER_Write failed\n");
        return HI_FAILURE;
    }

    return HI_SUCCESS;
}

HI_BOOL PLUG_MEDIA_RECORDMNG_GetState(HI_VOID)
{
    return gs_bRecord;
}

HI_S32 PLUG_MEDIA_RECORDMNG_Deinit(HI_VOID)
{
    //去初始化媒体通道
    HI_S32 s32Ret = HI_SUCCESS;
    PLUG_MEDIA_VPSSCFG_S stVpssCfg = { 0 };
    PLUG_MEDIA_VENCCFG_S stVencCfg = { 0 };
    s32Ret = RECORDMNG_GetVpssCfg(&stVpssCfg);
    if (HI_SUCCESS != s32Ret)
    {
        LOGE("PHOTOMNG_GetVpssCfg failed\n");
    }

    s32Ret = RECORDMNG_GetVencCfg(&stVencCfg);
    if (HI_SUCCESS != s32Ret)
    {
        LOGE("RECORDMNG_GetVencCfg failed\n");
    }

    s32Ret = SAMPLE_COMM_VPSS_UnBind_VENC(stVpssCfg.s32VpssGrp, stVpssCfg.s32VpssChn, stVencCfg.s32VencChn);
    if (s32Ret != HI_SUCCESS)
    {
        SAMPLE_PRT("SAMPLE_COMM_VENC_Stop failed with %#x!\n", s32Ret);
    }

    s32Ret= SAMPLE_COMM_VENC_Stop(stVencCfg.s32VencChn);
    if (s32Ret != HI_SUCCESS)
    {
        SAMPLE_PRT("SAMPLE_COMM_VENC_Stop failed with %#x!\n", s32Ret);
    }

    s32Ret =SAMPLE_COMM_VI_UnBind_VPSS(0, 0,stVpssCfg.s32VpssGrp);
    if (s32Ret != HI_SUCCESS)
    {
        SAMPLE_PRT("SAMPLE_COMM_VI_UnBind_VPSS failed with %#x!\n", s32Ret);
    }

    s32Ret = HI_MPI_VPSS_DisableChn(stVpssCfg.s32VpssGrp, stVpssCfg.s32VpssChn);
    if (s32Ret != HI_SUCCESS)
    {
        SAMPLE_PRT("HI_MPI_VPSS_DisableChn failed with %#x!\n", s32Ret);
    }

    s32Ret = HI_MPI_VPSS_StopGrp(stVpssCfg.s32VpssGrp);
    if (s32Ret != HI_SUCCESS)
    {
        SAMPLE_PRT("HI_MPI_VPSS_StopGrp failed with %#x!\n", s32Ret);
    }

    s32Ret = HI_MPI_VPSS_DestroyGrp(stVpssCfg.s32VpssGrp);
    if (s32Ret != HI_SUCCESS)
    {
        SAMPLE_PRT("HI_MPI_VPSS_DestroyGrp failed with %#x!\n", s32Ret);
    }

    s32Ret = FMP4MUXER_DeInit();
    if (HI_SUCCESS != s32Ret)
    {
        LOGE("FMP4MUXER_DeInit failed\n");
        return HI_FAILURE;
    }

    return HI_SUCCESS;
}

#ifdef __cplusplus
#if __cplusplus
}
#endif
#endif /* End of #ifdef __cplusplus */

